/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package TemplateParser;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import utils.PrivilegedAccessor;

/**
 *
 * @author valiadam
 */
public class TemplateParsingServlet extends HttpServlet {
   
    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try 
        {
            out.print("Create some templates and parse them!");
           
        } finally { 
            out.close();
        }
    }    

    // <editor-fold desc="Template Parsing Methods by valiadam.">

    /**
     * Parses the HTML code at the specified path and replaces
     * <--servlet.method--> with the result of the respective method call.
     *
     * Callable methods must have the following prototype: String method(HttpServletRequest request)
     *
     * @param strTemplatePath the path of the HTML code
     * @return the resulting HTML code after the markers have been replaced with
     * the result of the respective method calls
     */
    protected String parseTemplateFile (String strTemplatePath, HttpServletRequest request)
    {
        try
        {
         String strTemplateText = readFile(strTemplatePath);
         return parseTemplate(strTemplateText, request);
        }
        catch(IOException ex) {
            Logger.getLogger(TemplateParsingServlet.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    /**
     * Parses the given template html and replaces <--servlet.method--> with the
     * result of the respective method call.
     *
     * Callable methods must have the following prototype: String method(HttpServletRequest request)
     *
     * @param strTemplate: the HTML code to be parsed
     *
     * @return the resulting HTML code after the markers have been replaced with
     * the result of the respective method calls
     */
    protected String parseTemplate(String strTemplate, HttpServletRequest request)
    {
        String strResult;
        String [] calls = strTemplate.split(ServerCallPatternBegin);
        //calls now contains: "blabla0", "call1-->blabla1", "call2-->blabla2"...
        if (calls.length == 0)
            return null;
        else if (calls.length == 1)
            return calls[0];

        strResult = calls[0];

        //parse the tokens in calls and replace methods with result
        for (int i=1; i<calls.length;i++)
        {
            String strMethName = ParseGetMethodName(calls[i]);
            strResult += CallNamedMethod(strMethName, request) + ParseGetRemainingText(calls[i]);
        }

        return strResult;
    }

    // parsing helper methods:

    /**
     * Parses the input string and returns the contained method name
     * @param string the input string beginning with method-->
     * @return the method name
     */
    protected String ParseGetMethodName(String string)
    {
        if (string == null)
            return "";

        int nMethEnd = string.indexOf(ServerCallPatternEnd);
        if (nMethEnd == -1)
            return "";

        return string.substring(0, nMethEnd);
    }

    /**
     * Calls this.strMethName
     * @param strMethName the name of the method to be called
     * Note: the method must have the following prototype: String method(HttpServletRequest request)
     * @return
     */
    protected String CallNamedMethod(String strMethName, HttpServletRequest request)
    {
        if (strMethName == null)
            return "";
        try {
            String strRes = (String) PrivilegedAccessor.invokeMethod(this, strMethName, (Object)request);
            return strRes;
        } catch (NoSuchMethodException ex) {
            Logger.getLogger(TemplateParsingServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(TemplateParsingServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(TemplateParsingServlet.class.getName()).log(Level.SEVERE, null, ex);
        }

        return "";
    }

    /**
     * Parses the input string for the remaining text
     * @param string the input string
     * @return the remaining text after the method name has been removed
     */
    protected String ParseGetRemainingText(String string)
    {
        if (string == null)
            return "";

        int nMethEnd = string.indexOf(ServerCallPatternEnd);
        if (nMethEnd == -1)
            return string;

        int nRemainingTextBeginIndex = nMethEnd + ServerCallPatternEnd.length();
        if (nRemainingTextBeginIndex > string.length())
            return "";

        return string.substring(nRemainingTextBeginIndex);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="File reading to string">
    protected String readFile(String path) throws IOException
    {
        ServletContext context = getServletContext();
        InputStream is = context.getResourceAsStream(path);
        if (is == null)
            throw new IOException("The file could not be loaded from the path: " + path);

        return convertStreamToString(is);
    }

    private String convertStreamToString(InputStream is)
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }

    // </editor-fold>

    protected static String ServerCallPatternBegin = "<!--servlet.";
    protected static String ServerCallPatternEnd = "-->";


    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    } 

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "This is a template parsing servlet";
    }// </editor-fold>



}
